//
//  DefaultValue.swift
//  XBasicKit
//
//  Created by x on 2024/8/26.
//

import Foundation

///
///通过使用 Swift 的 Codable 协议，在解码 JSON 数据时为属性提供默认值。这个机制结合了 protocol、property wrapper（属性包装器）和扩展，来处理缺失的键或值，提供默认值。
///
///
public protocol DefaultValue {
    associatedtype Value: Codable
    static var defaultValue: Value { get }
}
/*
 Default 结构体是一个属性包装器，它包装了一个类型为 T.Value 的值，这里的 T 需要遵循 DefaultValue 协议。
     •    这个包装器的主要作用是当解码 JSON 数据时，如果没有找到相应的值，就使用类型 T 定义的 defaultValue。
 */
@propertyWrapper
public struct Default<T: DefaultValue> {
    public var wrappedValue: T.Value
    // 提供一个初始化器，使用默认值进行初始化
    public init() {
        self.wrappedValue = T.defaultValue
    }

    // 提供一个初始化器，允许使用者设置一个自定义的初始值
    public init(wrappedValue: T.Value) {
        self.wrappedValue = wrappedValue
    }
}

/*
 Default 结构体扩展了 Codable 协议，以便它可以在解码时提供默认值。
     •    在解码的初始化方法中，使用 decoder 来获取一个单值容器，然后尝试解码 T 类型的数据。
     •    如果解码失败（例如：键缺失或数据格式不匹配），就使用 T.defaultValue 作为默认值。
 */
extension Default: Codable {
    public init(from decoder: any Decoder) throws {
        let container = try decoder.singleValueContainer()
        wrappedValue = (try? container.decode(T.Value.self)) ?? T.defaultValue
    }
}


// 解决解析Key缺失
/*
 这个扩展提供了一个便捷方法，用于解码类型为 Default<T> 的属性。
     •    如果指定的键不存在或解码失败，它将返回一个 Default(wrappedValue: T.defaultValue)，确保总是有一个有效的值。
 */
extension KeyedDecodingContainer {
    func decode<T>(_ type: Default<T>.Type,forKey key: Key) throws -> Default<T> where T: DefaultValue {
        try decodeIfPresent(type, forKey: key) ?? Default(wrappedValue: T.defaultValue)
    }
}

public extension Bool {
    enum False: DefaultValue {
        public static let defaultValue = false
    }
    enum True: DefaultValue {
        public static let defaultValue = true
    }
}

extension Int: DefaultValue{
    public static let defaultValue = 0
    
    enum Ten: DefaultValue {
        public static let defaultValue = 10
    }
}

extension Double: DefaultValue{
    public static let defaultValue = 0
    
    enum Ten: DefaultValue {
        static let defaultValue = 10
    }
}

extension String: DefaultValue{
    public static let defaultValue = ""
    
    enum Empty: DefaultValue {
        public static let defaultValue = ""
    }
}
/// 扩展 Array 类型，使其在元素类型遵循 Codable 协议时，也遵循 DefaultValue 协议。
/// •    默认返回一个空数组 [] 作为 defaultValue
extension Array: DefaultValue where Element: Codable  {
    public static var defaultValue: Array<Element> { [] }
}

extension Default {
    typealias False = Default<Bool.False>
    typealias True = Default<Bool.True>
    typealias TenInt = Default<Int.Ten>
    typealias TenDouble = Default<Int.Ten>
    typealias EmptyString = Default<String.Empty>
}

/// 使用方式
//struct Model {
//    @Default.False var falseValue: Bool
//    @Default.True var trueValue: Bool
//    @Default.TenInt var tenValue: Int
//    @Default<Int> var intValue: Int
//}
